package com.atguigu.gmall.product.service.impl;

import com.atguigu.gmall.common.cache.GmallCache;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.exception.GmallException;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.model.product.*;
import com.atguigu.gmall.product.mapper.*;
import com.atguigu.gmall.product.service.ManageService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.lettuce.core.RedisClient;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;


import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @Description: TODO
 * @Author: Mr.Cao
 * @DateTime: 2021/9/28 19:09
 * BMW F750GS
 **/
@Service
public class ManageServiceImpl  implements ManageService {

    @Autowired
    private BaseCategory1Mapper baseCategory1Mapper;
    @Autowired
    private BaseCategory2Mapper baseCategory2Mapper;
    @Autowired
    private BaseCategory3Mapper baseCategory3Mapper;
    @Autowired
    private BaseAttrInfoMapper baseAttrInfoMapper;
    @Autowired
    private BaseAttrValueMapper baseAttrValueMapper;
    @Autowired
    private BaseTrademarkMapper baseTrademarkMapper;
    @Autowired
    private BaseSaleAttrMapper baseSaleAttrMapper;

    @Autowired
    private SpuInfoMapper spuInfoMapper;
    @Autowired
    private SpuSaleAttrValueMapper spuSaleAttrValueMapper;
    @Autowired
    private SpuSaleAttrMapper spuSaleAttrMapper;
    @Autowired
    private SpuImageMapper spuImageMapper;
    @Autowired
    private SkuInfoMapper skuInfoMapper;

    /**
     * 获取一级分类
     * */
    @Override
    public List<BaseCategory1> getCategory1() {
        return baseCategory1Mapper.selectList(null);
    }
    /**
     * 获取二级分类
     * */
    @Override
    public List<BaseCategory2> getCategory2(long category1Id) {
        return baseCategory2Mapper.selectList(
                new QueryWrapper<BaseCategory2>().eq("category1_id",category1Id));
    }
    /**
     * 获取三级分类
     * */
    @Override
    public List<BaseCategory3> getCategory3(long category2Id) {
        return baseCategory3Mapper.selectList(
                new QueryWrapper<BaseCategory3>().eq("category2_id",category2Id));
    }
    /**
     * 根据分类id获取平台属性
     * */
    @Override
    public List<BaseAttrInfo> attrInfoList(long category1Id, long category2Id, long category3Id) {

        return baseAttrInfoMapper.selectBaseAttrInfoList(category1Id,category2Id,category3Id);
    }
    /**
     * 保存平台属性 :添加或修改
     * */
    @Override
    @Transactional //事务
    public void saveAttrInfo(BaseAttrInfo baseAttrInfo) {
        if (baseAttrInfo.getId()!=null){//修改表
            //先删除表中的数据 根据attr_id 删除
            baseAttrValueMapper.delete(new QueryWrapper<BaseAttrValue>().eq("attr_id",baseAttrInfo.getId()));
            //更新表
            baseAttrInfoMapper.updateById(baseAttrInfo);
        }else {//添加表
            //添加平台属性
            baseAttrInfoMapper.insert(baseAttrInfo);
        }
        //添加平台属性值表
        //获取属性值
        List<BaseAttrValue> attrValueList = baseAttrInfo.getAttrValueList();
        //判断属性值是否为空
        if (!CollectionUtils.isEmpty(attrValueList)){//不为空是执行操作
            //遍历集合
            attrValueList.forEach(item->{
                //设置外键
                item.setAttrId(baseAttrInfo.getId());
                baseAttrValueMapper.insert(item);
            });
        }

    }
    /**
     * 根据平台属性ID获取平台属性
     * */
    @Override
    public List<BaseAttrValue> getAttrValueList(long attrId) {
        return  baseAttrValueMapper.selectList(new QueryWrapper<BaseAttrValue>().eq("attr_id",attrId));
    }
    /**
     * 获取spu分页列表
     * */
    @Override
    public IPage<SpuInfo> selectPageSpuInfo(long page, long limit,long category3Id) {
        //创建分页对象
        Page<SpuInfo> spuInfoPage = new Page<>(page,limit);
        //分页查询
        IPage<SpuInfo> spuInfoIPage = spuInfoMapper.selectPage(spuInfoPage,new QueryWrapper<SpuInfo>().eq("category3_id",category3Id));
        return spuInfoIPage;
    }
    /**
     * 分页获取品牌列表
     * */
    @Override
    public IPage<BaseTrademark> baseTrademark(long page, long limit) {
        //创建分页对象
        Page<BaseTrademark> baseTrademarkPage = new Page<>(page,limit);
        IPage<BaseTrademark> pageList = baseTrademarkMapper.selectPage(baseTrademarkPage, null);
        return pageList;
    }
    /**
     * 保存品牌列表
     * */
    @Override
    public void baseTrademarkSave(BaseTrademark baseTrademark) {
        baseTrademarkMapper.insert(baseTrademark);
    }
    /**
     * 根据id查询品牌信息
     * */
    @Override
    public BaseTrademark getBaseTrademarkById(long id) {
        BaseTrademark baseTrademark = baseTrademarkMapper.selectById(id);
        return baseTrademark;
    }
    /**
     * 根据id 删除品牌列表
     * */
    @Override
    public void removeBaseTrademarkById(long id) {
        try {
            baseTrademarkMapper.deleteById(id);
        } catch (Exception e) {
            e.printStackTrace();
            throw new GmallException("删除失败",201);
        }
    }
    /**
     * 获取品牌列表 , 用于添加商品属性spu时回显
     * */
    @Override
    public List<BaseTrademark> getTrademarkList() {
        List<BaseTrademark> list = baseTrademarkMapper.selectList(null);
        return list;
    }
    /**
     * 获取销售属性,用于添加商品属性spu时回显
     * */
    @Override
    public List<BaseSaleAttr> baseSaleAttrList() {
        List<BaseSaleAttr> list = baseSaleAttrMapper.selectList(null);
        return list;
    }
    /**
     * 根据id 更新品牌信息
     * */
    @Override
    public void updateBaseTrademark(BaseTrademark baseTrademark) {
        try {
            baseTrademarkMapper.updateById(baseTrademark);
        } catch (Exception e) {
            e.printStackTrace();
            throw new GmallException("更新失败", ResultCodeEnum.FAIL.getCode());
        }
    }
    /**
     * 添加spu 商品列表,多表添加 spu_info,spu_images,spu_sale_attr,spu_sale_attr_value
     * */
    @Override
    @Transactional//事务注解
    public void saveSpuInfo(SpuInfo spuInfo) {
        //保存spu表
        spuInfoMapper.insert(spuInfo);//返回主键
        //保存spu图片
        List<SpuImage> spuImageList = spuInfo.getSpuImageList();//获取图片集合
        spuImageList.forEach(spuImage->{
            spuImage.setSpuId(spuInfo.getId());
            spuImageMapper.insert(spuImage);
        });
        //保存商品销售属性
        List<SpuSaleAttr> spuSaleAttrList = spuInfo.getSpuSaleAttrList();
        spuSaleAttrList.stream().forEach(spuSaleAttr ->{
            spuSaleAttr.setSpuId(spuInfo.getId());//设置外键
            spuSaleAttrMapper.insert(spuSaleAttr);//进行添加操作,回填主键
            List<SpuSaleAttrValue> spuSaleAttrValueList = spuSaleAttr.getSpuSaleAttrValueList();
            spuSaleAttrValueList.stream().forEach(spuSaleAttrValue ->{
                //保存商品销售属性值表
                spuSaleAttrValue.setSpuId(spuInfo.getId());
                spuSaleAttrValue.setSaleAttrName(spuSaleAttr.getSaleAttrName());
                spuSaleAttrValueMapper.insert(spuSaleAttrValue);
            });
        });
    }
    /**
     * 分页获取sku列表
     * */
    @Override
    public IPage<SkuInfo> getSkuPage(long page, long limit) {
        //创建分页对象
        Page<SkuInfo> SkuInfoPage = new Page<>(page,limit);
        IPage<SkuInfo> skuInfoIPage = skuInfoMapper.selectPage(SkuInfoPage,null);
        return skuInfoIPage;
    }

    /**
     * sku商品上架
     * */
    @Override
    public void onSale(Long skuId) {
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
        skuInfo.setIsSale(SkuInfo.ONSALE);
        skuInfoMapper.updateById(skuInfo);
        //todo 发消息给mq 添加索引库的商品
    }
    /**
     * sku商品下架
     */
    @Override
    public void cancelSale(Long skuId) {
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
        skuInfo.setIsSale(SkuInfo.NOSALE);
        skuInfoMapper.updateById(skuInfo);
        //todo 发消息给mq 删除索引库的商品
    }
    /**
     * 根据spuId获取图片列表
     * */
    @Override
    public List<SpuImage> spuImageList(long spuId) {
        List<SpuImage> list = spuImageMapper.selectList(new QueryWrapper<SpuImage>().eq("spu_id", spuId));
        return list;
    }

    /**
     * 根据spuId获取销售属性
     * */
    @Override
    public List<SpuSaleAttr> spuSaleAttrList(long spuId) {
        return spuSaleAttrMapper.spuSaleAttrList(spuId);
    }

    @Autowired
    private SkuImageMapper skuImageMapper;
    @Autowired
    private SkuAttrValueMapper skuAttrValueMapper;
    @Autowired
    private SkuSaleAttrValueMapper skuSaleAttrValueMapper;
    /**
     * 保存sku商品
     * */
    @Override
    @Transactional
    public void saveSkuInfo(SkuInfo skuInfo) {
        //添加sku_info表,并回填主键id
        skuInfoMapper.insert(skuInfo);
        //添加sku_image表
        skuInfo.getSkuImageList().stream().forEach(skuImage -> {
            skuImage.setSkuId(skuInfo.getId());//设置外键
            skuImageMapper.insert(skuImage);
        });
        //添加sku_attr_value表
        skuInfo.getSkuAttrValueList().stream().forEach(skuAttrValue -> {
            skuAttrValue.setSkuId(skuInfo.getId());
            skuAttrValueMapper.insert(skuAttrValue);
        });
        //添加sku_Sale_attr_value表
        skuInfo.getSkuSaleAttrValueList().stream().forEach(skuSaleAttrValue -> {
            skuSaleAttrValue.setSkuId(skuInfo.getId());
            skuSaleAttrValue.setSpuId(skuInfo.getSpuId());
            skuSaleAttrValueMapper.insert(skuSaleAttrValue);
        });

    }

    @Autowired
    private BaseCategoryViewMapper baseCategoryViewMapper;
    /**
     * 根据ID查询skuInfo表
     */
/*    @Override
    public SkuInfo getSkuInfoById(long skuId) {
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
        if (skuInfo!=null){
            //查询图片集合
            List<SkuImage> skuImageList = skuImageMapper.selectList(new QueryWrapper<SkuImage>().eq("sku_id", skuId));
            skuInfo.setSkuImageList(skuImageList);
        }
        return skuInfo;
    }*/
    @Autowired
   private RedisTemplate redisTemplate;
    @Autowired
    private RedissonClient redissonClient;
    /**
     * 根据ID查询skuInfo表 先查询redis缓冲  并解决缓存的三大问题 缓存的击穿 雪崩 穿透
     */
    @Override
    public SkuInfo getSkuInfoById(long skuId) {
        String cacheKey = RedisConst.SKUKEY_PREFIX + skuId + RedisConst.SKUKEY_SUFFIX;//RedisKey的规范
        String cacheKeyLock = RedisConst.SKUKEY_PREFIX + skuId + RedisConst.SKULOCK_SUFFIX;//RedisKey的规范
        //1:先查询缓存
        SkuInfo skuInfo = (SkuInfo) redisTemplate.opsForValue().get(cacheKey);
        if (null == skuInfo) {
            RLock lock = redissonClient.getLock(cacheKeyLock);//cacheKeyLock : 锁的名称
            //参数1：尝试多久  获取锁
            //参数2：  获取锁持有时间  (死锁）
            try {
                boolean isLock = lock.tryLock(RedisConst.SKULOCK_EXPIRE_PX1,
                        RedisConst.SKULOCK_EXPIRE_PX2, TimeUnit.SECONDS);
                if(isLock){
                    // 查询DB
                    try {
                        skuInfo = skuInfoMapper.selectById(skuId);
                        if (null != skuInfo) {
                            //查询图片
                            skuInfo.setSkuImageList(skuImageMapper.selectList(new QueryWrapper<SkuImage>()
                                    .eq("sku_id", skuId)));
                            //4:保存缓存一份
                            redisTemplate.opsForValue().set(cacheKey,skuInfo,//缓存雪崩
                                    RedisConst.SKUKEY_TIMEOUT + new Random().nextInt(300)
                                    , TimeUnit.SECONDS);
                        }else{
                            //缓存的第一大问题 缓存穿透
                            skuInfo = new SkuInfo();//空结果  空对象
                            redisTemplate.opsForValue().set(cacheKey,skuInfo,5, TimeUnit.MINUTES);
                        }
                    } finally {
                        //解锁
                        lock.unlock();
                    }
                }else{
                    //没有上锁
                    TimeUnit.SECONDS.sleep(2);
                    return (SkuInfo) redisTemplate.opsForValue().get(cacheKey);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return skuInfo;
    }

    /**
     * 一二三级分类 查询id 和名称
     * */
    @Override
    @GmallCache
    public BaseCategoryView getCategory123(long category3Id) {
        BaseCategoryView baseCategoryView = baseCategoryViewMapper.selectById(category3Id);
        return baseCategoryView;
    }
    /**
     * 单独查询价格, 查询实时价格, 直接查询数据库中的价格, 不查询缓存中的价格
     * */
    @Override
    public BigDecimal getPrice(long skuId) {
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
        if (skuInfo!=null){
            BigDecimal price = skuInfo.getPrice();
            return price;
        }
        return null;
    }
    /**
     *根据spuId，skuId 查询销售属性集合
     * 查询销售属性及选中的属性
     */
    @Override
    @GmallCache(prefix = "getSpuSaleAttrListCheckBySku")
    public List<SpuSaleAttr> getSpuSaleAttrListCheckBySku(Long skuId, Long spuId) {
        List<SpuSaleAttr> list =  spuSaleAttrMapper.getSpuSaleAttrListCheckBySku(skuId,spuId);
        return list;
    }
    /**
     *  根据spuId 查询map 集合属性 组合与对应skuId
     * */
    @Override
    @GmallCache(prefix = "getSkuValueIdsMap")
    public Map getSkuValueIdsMap(Long spuId) {
        Map<Object, Object> map = new HashMap<>();
        // key = 125|123 ,value = 37
        List<Map> mapList = skuSaleAttrValueMapper.getSaleAttrValuesBySpu(spuId);
        if (mapList != null && mapList.size() > 0) {
            // 循环遍历
            for (Map skuMap : mapList) {
                // key = 125|123 ,value = 37
                map.put(skuMap.get("value_ids"), skuMap.get("sku_id"));
            }
        }
        return map;

    }
    /**
     * 查询所有分类视图 集合
     * */
    @Override
    public List<BaseCategoryView> getBaseCategoryViewList() {
         return baseCategoryViewMapper.selectList(null);
    }

    /**
     * 根据品牌ID查询品牌信息
     * */
    @Override
    public BaseTrademark getBaseTrademark(Long tmId) {
        return baseTrademarkMapper.selectById(tmId);
    }

    /**
     * 查询某某款 sku商品的平台属性集合
     * */
    @Override
    public List<SkuAttrValue> getSkuAttrValueAndAttrAndAttrValue(long skuId) {
        return skuAttrValueMapper.getSkuAttrValueAndAttrAndAttrValue(skuId);
    }
}
